package svc

import (
	"context"
	"fmt"
	"property_service/internal/config"
	"time"

	"github.com/zeromicro/go-zero/core/logx"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"gorm.io/gorm/schema"
)

type ServiceContext struct {
	Config      config.Config
	Gorm        *gorm.DB
	DataSources map[string]*gorm.DB
	Ctx         context.Context
}

func NewServiceContext(c config.Config) *ServiceContext {
	dataSources := make(map[string]*gorm.DB)
	if c.Databases.MultipleDataSourcesStatus() {
		if c.Databases.DataSources != nil {
			for _, datasource := range c.Databases.DataSources {
				name, directory, err := datasource.ChoiceType()

				if err != nil {
					logx.Info(err)
					continue
				}

				db, err := connDatabases(directory, "cloud_", true, nil)
				if db == nil {
					logx.Info(err)
					continue
				}
				dataSources[name] = db
			}
			fmt.Println("\t多数据源以启用\t")
		}
	}

	var conn *gorm.DB
	var err error
	if c.Databases.PrimaryDatabasesStatus() {
		conn, err = connectWithRetry(c.Databases.ChoiceType(), "cloud_", true, 5, 2*time.Second)
		if conn == nil || err != nil {
			panic(err)
		}
	}
	return &ServiceContext{
		Config:      c,
		Gorm:        conn,
		DataSources: dataSources,
	}
}

func connectWithRetry(
	directory gorm.Dialector,
	tablePrefix string,
	singularTable bool,
	maxRetries int,
	retryDelay time.Duration,
) (*gorm.DB, error) {
	var db *gorm.DB
	var err error

	for i := 0; i < maxRetries; i++ {
		db, err = connDatabases(directory, tablePrefix, singularTable, nil)
		if err == nil {
			return db, nil
		}

		logx.Errorf("Failed to connect to database (attempt %d/%d): %v", i+1, maxRetries, err)
		time.Sleep(retryDelay)
	}
	return nil, fmt.Errorf("could not connect to database after %d attempts: %v", maxRetries, err)
}

func connDatabases(
	directory gorm.Dialector,
	tablePrefix string,
	singularTable bool,
	loggers ...logger.Interface,
) (*gorm.DB, error) {
	//var newLogger logger.Interface
	//if loggers == nil || len(loggers) != 1 {
	//	newLogger = &CustomLogger{
	//		Interface: logger.Default.LogMode(logger.Silent),
	//	}
	//} else {
	//	newLogger = loggers[0]
	//}

	db, err := gorm.Open(directory, &gorm.Config{
		Logger: logger.Default.LogMode(logger.Info),
		NamingStrategy: schema.NamingStrategy{
			TablePrefix:   tablePrefix,
			SingularTable: singularTable,
		},
	})
	if err != nil {
		return nil, err
	}

	// 配置连接池
	sqlDB, err := db.DB()
	if err != nil {
		return nil, err
	}
	sqlDB.SetMaxIdleConns(10)             // 设置空闲连接池中的最大连接数
	sqlDB.SetMaxOpenConns(100)            // 设置打开的最大连接数
	sqlDB.SetConnMaxLifetime(time.Second) // 设置连接的最大可复用时间

	return db, nil
}
